#include <stdio.h>
#include <string.h>

#include "..//include//createvfs.h"
#include "..//include//n_ary.h"
#include "..//include//vfs_errorcodes.h"
#include "..//include//fileOperations.h"

struct Block b;
struct header headervar;
struct FD file_desc;

FILE *fp_src;
FILE *fp_dest;


int copyfileop(char source_file_path[] , char dest_dir_path[], char filename_g[]){

	int i, j;
	char dest_filename[100];
	char dest_type[4];
	int dest_blockno;
	int flag_src;
	int flag_dest;
	int new_blockno;
	char *fname;
	char *fpath;
	char data[1024];
	
	fname = get_fname(dest_dir_path);
	fpath = get_abspath(dest_dir_path);
	
	if ((strcmp(source_file_path,"") == 0) || (strcmp(dest_dir_path,"") == 0)){
		printf("copyfile_FAILURE %s\n",ERR_VFS_COPYFILE_00);
		return 0;
	}
	
	

	fp_dest = fopen(filename_g, "rb+");
	
	

	if (fp_dest == NULL){
		printf("copyfile_FAILURE %s\n",ERR_VFS_COPYFILE_02);
		return 0;
	}
	
	

	else{
	
		rewind (fp_dest);
        	fread(&headervar, sizeof(struct header), 1, fp_dest);
        	
        	if (headervar.used_desc == TOTAL_DESC || num_used_blocks == num_blocks)
        	{
           		printf("copyfile_FAILURE %s\n",ERR_VFS_COPYFILE_04); // File system FULL
           		return 0;

        	}
	
		rewind (fp_dest);
		fseek (fp_dest, (LABEL_SIZE*sizeof(char) + 2*(sizeof(int))), SEEK_SET);
		
				for(j=1; j<=TOTAL_DESC; j++){
			 		fread (&file_desc, sizeof(struct FD), 1, fp_dest);
			 		
			 		if(strcmp(file_desc.path,dest_dir_path)==0){			 			
			 			flag_dest=0;			 			
			 		} 	
			 		
			 		if(strcmp(file_desc.path,source_file_path)==0){			 			
			 			flag_src=0;
			 		} 		 		
			 				 		
			 	}
			 	
		if(flag_src!=0){
			printf("copyfile_FAILURE %s\n",ERR_VFS_COPYFILE_01);
			return 0;		
		}
		
		else if(flag_dest!=0){
			printf("copyfile_FAILURE %s\n",ERR_VFS_COPYFILE_02);
			return 0;		
		}
		
		else{

			rewind (fp_dest);
			fseek (fp_dest, (LABEL_SIZE*sizeof(char) + 2*(sizeof(int))), SEEK_SET);

			 	for(j=1; j<=TOTAL_DESC; j++){

			 		fread (&file_desc, sizeof(struct FD), 1, fp_dest);

			 		if(strcmp(file_desc.path,source_file_path)==0){

			 			strcpy(dest_filename,file_desc.name);
			 			strcpy(dest_type, file_desc.type);
			 			dest_blockno = file_desc.blockno;

			 			break;
			 		}

			 	}


			 	// Get the location of a new free block
			 	rewind(fp_dest);
				fseek(fp_dest, sizeof(struct header), SEEK_SET);
				fread(&freelist, sizeof(freelist), 1, fp_dest);
			 	for(i=0; i<num_blocks; i++){

					if(freelist[i] == 0) new_blockno = i+1;
				}
				
				rewind (fp_dest);
				fseek (fp_dest, LABEL_SIZE*sizeof(char) + 2*(sizeof(int)) + sizeof(struct FD), SEEK_SET);

			 	// Write to an empty FD
			 	for(j=2; j<=TOTAL_DESC; j++){

			 		fread (&file_desc, sizeof(struct FD), 1, fp_dest);

			 		if(strcmp(file_desc.name,"\0")==0){

			 			strcpy(file_desc.path,dest_dir_path);
			 			strcpy(file_desc.name,dest_filename);
			 			strcpy(file_desc.type,dest_type);
			 			file_desc.blockno = dest_blockno;

			 			// Write to FD

			 		fseek (fp_dest, (LABEL_SIZE*sizeof(char) + 2*(sizeof(int)))+ sizeof(struct FD)*(j-1), SEEK_SET);
		  				fwrite(&file_desc, sizeof(struct FD), 1, fp_dest);
  						rewind (fp_dest);

						// Update no. of used descriptors

						rewind (fp_dest);
						fread(&headervar, sizeof(struct header), 1, fp_dest);
						headervar.used_desc = headervar.used_desc+1;
						rewind (fp_dest);
						fwrite(&headervar, sizeof(struct header), 1, fp_dest);


			 			break;
			 		}
			 	}


			 // Read the data from the block

			 rewind(fp_dest);
			 fseek(fp_dest,sizeof(struct header)+(sizeof(freelist))+sizeof(struct Block)*(dest_blockno-1),SEEK_SET);
			 fread(&b, sizeof(struct Block), 1, fp_dest);
			 strcpy(data, b.blk);

			 // Write the data to the new block

			 rewind(fp_dest);
			 fseek(fp_dest,sizeof(struct header)+(sizeof(freelist))+sizeof(struct Block)*(new_blockno-1),SEEK_SET);
			 strcpy(b.blk,data);
			 fwrite(&b, sizeof(struct Block), 1, fp_dest);
			 
			 num_used_blocks = num_used_blocks + 1;
			 
			 // Add to the data structures
			 
			 root = insert(root,dest_dir_path);
			 //printf("CHECKS: %s, %s\n",fname,fpath);
    			 hashfile(fname,fpath);
		}

	}

	return 1;

}

